﻿
; --------------------------------------------------------------------
;        <<  声明常量  >>
; --------------------------------------------------------------------
; 注册表
; Software\microld\node
; 在x64位系统下会指向 Software\Wow6432Node\microld\node
; 但不影响判断
!define GREEN_PATH_KEY "Software\microld"
!define SYSTEM_PATH_KEY "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
!define  /date DATE "%m%d"
!define  Version "1.0.0.${DATE}"

; --------------------------------------------------------------------
;        <<  声明变量  >>
; --------------------------------------------------------------------
Var Microld
; 绿化变量
Var CORE_NAME
Var CORE_VERSION
Var CORE_PUBLISHER
Var CORE_WEBSITE
; 产品变量
Var PRODUCT_NAME
Var PRODUCT_VERSION
Var PRODUCT_UPDATE
; 包管理
; package manager
Var PACKAGE_NAME
Var PACKAGE_SOURCE
Var PACKAGE_VERSION
Var PACKAGE_UPDATE
; 环境
Var ARCHITECTURE
Var PATH
; 判断
Var isSoftware
Var isGreen
Var isNpm
; 升级
Var nodeUpdate
Var npmUpdate
; 路径
Var npmPath
Var nodePath
; 透明度
Var TRANSPARENT
; UI > ICON
Var hCtl_UI_Icon
Var hCtl_Clean_Icon
; UI > Title
Var hCtl_UI_Title
Var hCrl_Title_Font
Var hCrl_Product_Version
; UI > Group
Var hCrl_Group_Box
Var hCrl_Group_Line
; UI > Button
Var hCrl_Button_Green
Var hCrl_Button_Exit
; UI > CheckBOX
Var hCrl_Check_Source
Var hCrl_Check_Source_Status
Var hCrl_Source
Var hCrl_Check_Update
Var hCrl_Check_Update_Status
Var hCrl_Check_Other
; UI > Link
Var hCrl_Link_Author


; --------------------------------------------------------------------
;        <<  包含文件  >>
; --------------------------------------------------------------------
!include "x64.nsh"
!include "MUI2.nsh"
!include "FileFunc.nsh"
!include "LogicLib.nsh"
!include "WordFunc.nsh"
; Windows API
!include "WinMessages.nsh"
!include "WinCore.nsh"


; --------------------------------------------------------------------
;        <<  脚本配置  >>
; --------------------------------------------------------------------

; 使7-Zip打开看不到其他内容。
!packhdr temp.dat 'cmd /c Copy /B temp.dat /B +resource\Microld.7z temp.dat'

; 压缩率
SetCompressor /SOLID lzma
SetCompressorDictSize 32

; 提升安装程序权限(vista,win7,win8)
RequestExecutionLevel admin

; 输出文件
OutFile "release\Green.exe"

; 加载模板
!define MUI_UI "resource\ui.exe"

; 图标文件
!define MUI_ICON "extra\Green.ico"

; 标题
Name "$PRODUCT_NAME"
Caption "$(^Name)绿化"

; 语言
!insertmacro MUI_LANGUAGE "SimpChinese"
!insertmacro GetParameters

; 调用自定义页面
Page custom customPage

; 版本版权信息
VIProductVersion "${Version}"
VIAddVersionKey /LANG=2052  "ProductName"      "node绿化工具"           ; 产品名称
VIAddVersionKey /LANG=2052  "ProductVersion"   "${Version}"             ; 产品版本
VIAddVersionKey /LANG=2052  "FileDescription"  "node绿化工具"           ; 描述
VIAddVersionKey /LANG=2052  "LegalTrademarks"  "Microld"                ; 商标
VIAddVersionKey /LANG=2052  "LegalCopyright"   "© 2015 Microld"         ; 版权
VIAddVersionKey /LANG=2052  "OriginalFilename" "Green.exe"              ; 源文件名







; --------------------------------------------------------------------
;        <<  区段  >>
; --------------------------------------------------------------------
Section
  DetailPrint "Microld"
SectionEnd


; --------------------------------------------------------------------
;        <<  预处理段  >>
; --------------------------------------------------------------------
Function .onInit
  ;
  SetOutPath "$TEMP\Green"
  File /r extra\*.*
  SetOutPath $TEMP

  IfFileExists $EXEDIR\Config.ini +2 0
    CopyFiles "$TEMP\Green\Config.ini" "$EXEDIR\Config.ini"
  Nop

  Call ReadIni
  Call GetSystemInfo

  ; 创建互斥防止重复运行
  System::Call 'kernel32::CreateMutexA(i 0, i 0, t "autocall_installer") i .r1 ?e'
    Pop $R0
    StrCmp $R0 0 +3 ;0代表本行
      MessageBox MB_OK|MB_ICONEXCLAMATION "Error! $\n  \
        已经有一个绿化工具正在运行！"
      Abort
    Nop ; 未运行多个绿化程序
      StrCpy $R0 "0"

  ; 不是我绿化的
  ${If} $isGreen == '0'
    ; 存在node
    ${If} $isSoftware == '0'
      MessageBox MB_OK|MB_ICONEXCLAMATION "Error $\n  \
        Hello, 朋友你电脑中存在 $PRODUCT_NAME！$\n  \
        如果想安装此版本, 请先卸载原有 $PRODUCT_NAME!"
      Abort
    ${EndIf}
  ${EndIf}

  ; 判断 node 是否存在
  StrCpy $R0 "0"
  IfFileExists $EXEDIR\node\$ARCHITECTURE\node.exe 0 +2
    StrCpy $R0 "1"
  Nop
    ; 文件不存在
  ${If} $R0 == '0'
    MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "Error $\n  \
      node文件不存在, 是否需要下载？" IDOK +2 IDCANCEL 0
      Abort
    Nop
      Call nodeUpdate
  ${EndIf}


  ; 判断 npm 是否存在
  StrCpy $R0 "0"
  IfFileExists $EXEDIR\module\node_modules\npm\bin\npm.cmd 0 +2
    StrCpy $R0 "1"
  Nop
    ; 文件不存在
  ${If} $R0 == '0'
    MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "Error $\n  \
      npm文件不存在, 是否需要下载？" IDOK +2 IDCANCEL 0
      Abort
    Nop
      Call npmUpdate
      Call modRegistry
  ${EndIf}
FunctionEnd

; --------------------------------------------------------------------
;        <<  自定义界面  >>
; --------------------------------------------------------------------
Function customPage

  Call ReadIni
  Call GetSystemInfo

  nsDialogs::Create 1018

  ; 透明
  IntOp $R8 $TRANSPARENT * 255
  IntOp $R8 $R8 / 100
  System::Call "user32::SetWindowPos(i $HWNDPARENT, i -1, i0, i0, i0, i0, i 3)"
  StrCpy $R2 $R8  ;透明度（0-255）
  System::Call 'User32::GetWindowLong(i $HWNDPARENT, i -20) .iR0'
  IntOp $R0 $R0 + 0x80000
  System::Call 'User32::SetWindowLong(i $HWNDPARENT, i -20, i R0) .iR1'
  System::Call 'User32::SetLayeredWindowAttributes(i $HWNDPARENT, i 0, i R2, i 2) .i R0'


  ; 隐藏最大化 & 最小化
  System::Call 'user32::GetWindowLong(i $hwndparent,i -16)i.r0'
  intop $1 0x30000 ~
  intop $0 $0 & $1
  System::Call 'user32::SetWindowLong(i $hwndparent,i -16,i $0)i' ;最大化不可用

  Pop $Microld
  ${If} $Microld == error
  Abort
  ${EndIf}


  ; === Icon ===
  ${NSD_CreateIcon} 6u 1u 21u 19u ""
  Pop $hCtl_UI_Icon
  ${NSD_SetIcon} $hCtl_UI_Icon "$TEMP\Green\Green.ico" $hCtl_Clean_Icon
  ${NSD_FreeImage} $hCtl_Clean_Icon


  ; === Label : Title  ===
  ${NSD_CreateLabel}  33u 1u 93u 19u "$PRODUCT_NAME $CORE_NAME"
  Pop $hCtl_UI_Title
  CreateFont $hCrl_Title_Font "Microsoft JhengHei" "12" "700"
  SendMessage $hCtl_UI_Title ${WM_SETFONT} $hCrl_Title_Font 0
  SetCtlColors $hCtl_UI_Title 0x3399FF transparent

  ; === Label : Product  ===
  ${NSD_CreateLabel}  33u 16u 93u 9u "$PRODUCT_NAME@$PRODUCT_VERSION $PACKAGE_NAME@$PACKAGE_VERSION"
  Pop $hCrl_Product_Version

  ; === GroupBox : Box  ===
  ${NSD_CreateGroupbox} 3u 22u 126u 64u ""
  Pop $hCrl_Group_Box

  ; === GroupBox : Line  ===
  ${NSD_CreateGroupbox} 1u 88u 128u 5u ""
  Pop $hCrl_Group_Line

  ; === Button : Exit ===
  ${NSD_CreateButton} 74u 96u 49u 13u "退出"
    Pop $hCrl_Button_Exit
    ${NSD_OnClick} $hCrl_Button_Exit exitGreen

  ; === Button : Green && Unstall ===
  ${NSD_CreateButton} 14u 30u 104u 19u "卸载"
    Pop $hCrl_Button_Green
    EnableWindow $hCrl_Button_Green 0
  ${If} $isSoftware == '0' ; 系统中存在node
    ${if} $isGreen == '1' ; 是我绿化的
      SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:卸载"
      EnableWindow $hCrl_Button_Green 1
      ${NSD_OnClick} $hCrl_Button_Green uInstall
    ${EndIf}
  ${Else}  ; 系统中不存在node
    SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:绿化"
    EnableWindow $hCrl_Button_Green 1
    ${NSD_OnClick} $hCrl_Button_Green Install
  ${EndIf}
  CreateFont $R0 "宋体" "10" "500"
  SendMessage $hCrl_Button_Green ${WM_SETFONT} $R0 0


  ; === CheckBox : Source ===
  ${NSD_CreateCheckBox} 18u 52u 104u 11u "淘宝源"
    Pop $hCrl_Check_Update
    EnableWindow $hCrl_Check_Update 0

  ; === CheckBox : Update ===
  ${NSD_CreateCheckBox} 18u 62u 104u 11u "更新node"
    Pop $hCrl_Check_Source
    EnableWindow $hCrl_Check_Source 0

  ; === CheckBox : UNLL ===
  ${NSD_CreateCheckBox} 18u 72u 104u 11u "更新npm"
    Pop $hCrl_Check_Other
    EnableWindow $hCrl_Check_Other 0

  ; === Link : About ===
  ${NSD_CreateLink} 8u 98u 30u 9u "$CORE_PUBLISHER"
    Pop $hCrl_Link_Author
    ${NSD_OnClick} $hCrl_Link_Author openURL

;  ${NSD_CreateComboBox} 8.13u 35.33u 81.98u 13.33u ""
;    Pop $hCtl_Green_ComboBox
;    ${NSD_CB_AddString} $hCtl_Green_ComboBox "v4.1.2"
;    ${NSD_CB_AddString} $hCtl_Green_ComboBox "v4.2.1"
;    ${NSD_CB_SelectString} $hCtl_Green_ComboBox "v4.2.1"

  nsDialogs::Show
FunctionEnd


Function Install

  Call ReadIni
  Call GetSystemInfo

  EnableWindow $hCrl_Button_Green 0
  SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:绿化中..."

  ; 环境注册表
  WriteRegStr HKLM "${SYSTEM_PATH_KEY}"            "node_home"     "$EXEDIR\node\$ARCHITECTURE"
  WriteRegStr HKLM "${SYSTEM_PATH_KEY}"            "npm_home"      "$EXEDIR\module"
  WriteRegStr HKLM "${SYSTEM_PATH_KEY}"            "path"          "$PATH;$EXEDIR\node\$ARCHITECTURE;$EXEDIR\module;"
  ; node
  WriteRegStr HKLM "${GREEN_PATH_KEY}\node"        "name"          "$PRODUCT_NAME"
  WriteRegStr HKLM "${GREEN_PATH_KEY}\node"        "version"       "$PRODUCT_VERSION"
  WriteRegStr HKLM "${GREEN_PATH_KEY}\node"        "path"          "$EXEDIR\node\$ARCHITECTURE"
  ; npm
  WriteRegStr HKLM "${GREEN_PATH_KEY}\node\npm"    "path"          "$EXEDIR\module"
  ; 刷新注册表
  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment"
  ;SendMessage ${HWND_BROADCAST} ${WM_SETTINGCHANGE} 0 "STR:Environment"
  ; 写npmrc文件
  Call modRegistry

  MessageBox MB_OK|MB_ICONEXCLAMATION "绿化完成"


  SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:卸载"
  ${NSD_OnClick} $hCrl_Button_Green uInstall
  EnableWindow $hCrl_Button_Green 1


FunctionEnd






Function uInstall

  Call ReadIni
  Call GetSystemInfo

  EnableWindow $hCrl_Button_Green 0
  SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:卸载中..."

  ${WordReplace} $PATH ";$nodePath;" "" "+" $PATH
  ${WordReplace} $PATH "$npmPath;"   "" "+" $PATH
  ${WordReplace} $PATH ";;"          "" "+" $PATH

  WriteRegStr    HKLM "${SYSTEM_PATH_KEY}" "path"      "$PATH"
  DeleteRegValue HKLM "${SYSTEM_PATH_KEY}" "npm_path"
  DeleteRegValue HKLM "${SYSTEM_PATH_KEY}" "node_path"
  DeleteRegKey   HKLM "${GREEN_PATH_KEY}"

  SetOutPath $TEMP
  Delete $EXEDIR\module\node_modules\npm\npmrc
  RMDir $TEMP\Green

  SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment"

  MessageBox MB_OK|MB_ICONEXCLAMATION "卸载完成"

  SendMessage $hCrl_Button_Green ${WM_SETTEXT} 0 "STR:绿化"
  ${NSD_OnClick} $hCrl_Button_Green Install
  EnableWindow $hCrl_Button_Green 1

FunctionEnd


Function modRegistry

  IfFileExists $EXEDIR\module\node_modules\npm\npmrc 0 +2
    Delete $EXEDIR\module\node_modules\npm\npmrc
  Nop

  ; 写文件
  FileOpen $R0 $EXEDIR\module\node_modules\npm\npmrc w
    FileWrite $R0 "prefix=$EXEDIR\module$\r$\n"
    FileWrite $R0 "cache=$EXEDIR\cache$\r$\n"
  ${If} $PACKAGE_SOURCE == "taobao"
    FileWrite $R0 "registry=http://registry.npm.taobao.org/"
  ${EndIf}
  FileClose $R0
FunctionEnd

Function nodeUpdate

  IfFileExists $EXEDIR\node\*.* 0 +2
    RMDir /r $EXEDIR\node
  Nop
  CreateDirectory $EXEDIR\node\x64
  CreateDirectory $EXEDIR\node\x86

  nsExec::Exec '\
    "$TEMP\Green\curl.exe" \
    -L \
    -# \
    "http://npm.taobao.org/mirrors/node/$PRODUCT_VERSION/win-x64/node.exe" \
    -o "$EXEDIR\node\x64\node.exe"\
  '

  nsExec::Exec '\
    "$TEMP\Green\curl.exe" \
    -L \
    -# \
    "http://npm.taobao.org/mirrors/node/$PRODUCT_VERSION/win-x86/node.exe" \
    -o "$EXEDIR\node\x86\node.exe"\
  '
FunctionEnd

Function npmUpdate
  SetOutPath $TEMP
  IfFileExists $EXEDIR\module\node_modules\*.* +2 0
    CreateDirectory $EXEDIR\module\node_modules
  Nop

  IfFileExists $EXEDIR\module\node_modules\npm\*.* 0 +2
    RMDir /r $EXEDIR\module\node_modules\npm
  Nop

  nsExec::Exec '\
    "$TEMP\Green\curl.exe" \
    -L \
    -# \
    "http://npm.taobao.org/mirrors/npm/$PACKAGE_VERSION.zip" \
    -o "$EXEDIR\module\node_modules\$PACKAGE_VERSION.zip" \
  '

  nsExec::Exec '\
    "$TEMP\Green\7z.exe" \
    x "$EXEDIR\module\node_modules\$PACKAGE_VERSION.zip" \
    -o"$EXEDIR\module\node_modules" \
    -y \
    -aos \
  '
  Delete "$EXEDIR\module\node_modules\$PACKAGE_VERSION.zip"

  ${WordReplace} $PACKAGE_VERSION "v" "" "+" $R0
  Rename $EXEDIR\module\node_modules\npm-$R0 $EXEDIR\module\node_modules\npm

  CopyFiles "$EXEDIR\module\node_modules\npm\bin\npm.cmd" "$EXEDIR\module\npm.cmd"
  CopyFiles "$EXEDIR\module\node_modules\npm\bin\npm" "$EXEDIR\module\npm"

  Call modRegistry
FunctionEnd


Function exitGreen
  MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION "Hello $\n  \
      朋友你确定要关闭我！" IDOK 0 IDCANCEL +2
    sendmessage $HWNDPARENT ${wm_close} 0 0
  Nop
FunctionEnd

Function openURL
  ExecShell "open" "$CORE_WEBSITE"
FunctionEnd


Function ReadIni
  ; 读取INI > 产品
  ReadINIStr $PRODUCT_NAME    "$EXEDIR\config.ini" "product" "name"
  ReadINIStr $PRODUCT_VERSION "$EXEDIR\config.ini" "product" "version"
  ReadINIStr $PRODUCT_UPDATE  "$EXEDIR\config.ini" "product" "update"
  ; 读取INI > 包管理
  ReadINIStr $PACKAGE_NAME    "$EXEDIR\config.ini" "package" "name"
  ReadINIStr $PACKAGE_SOURCE  "$EXEDIR\config.ini" "package" "source"
  ReadINIStr $PACKAGE_VERSION "$EXEDIR\config.ini" "package" "version"
  ReadINIStr $PACKAGE_UPDATE  "$EXEDIR\config.ini" "package" "update"
  ; 读取INI > 绿化程序
  ReadINIStr $CORE_NAME       "$EXEDIR\config.ini" "core" "name"
  ReadINIStr $CORE_PUBLISHER  "$EXEDIR\config.ini" "core" "author"
  ReadINIStr $CORE_WEBSITE    "$EXEDIR\config.ini" "core" "website"

  ; 获取界面透明度
  ReadINIStr $TRANSPARENT     "$EXEDIR\config.ini" "core" "transparent"
  ${If} $TRANSPARENT < '50'
    StrCpy $TRANSPARENT "100"
  ${EndIf}
FunctionEnd

Function GetSystemInfo
  ; 系统构架
  ReadRegStr $R0 HKLM "${SYSTEM_PATH_KEY}" "PROCESSOR_ARCHITECTURE"
    StrCpy $ARCHITECTURE "x64"
    ${If} $R0 == "x86"
      StrCpy $ARCHITECTURE "x86"
    ${EndIf}

  ; 获取PATH
  ; ReadEnvStr $PATH PATH
  ReadRegStr $PATH HKLM "${SYSTEM_PATH_KEY}" "Path"

  ; 系统中是否存在NodeJS
  ; 存在 == 0 / 不存在 == error
  nsExec::Exec '"node" -v'      
    Pop $isSoftware

  ; 判断 包管理 存在
  nsExec::Exec '"npm" -v'      
    Pop $isNpm

  ; 判断是否我绿化的
  ReadRegStr $R0 HKLM "${GREEN_PATH_KEY}\node" "name"
    StrCpy $isGreen "0"
    ${If} $R0 == "node"
      StrCpy $isGreen "1"
    ${EndIf}

  ; 获取node PATH
  ReadRegStr $nodePath HKLM "${GREEN_PATH_KEY}\node" "path"

  ; 获取npm PATH
  ReadRegStr $npmPath  HKLM "${GREEN_PATH_KEY}\node\npm"  "path"


FunctionEnd


; ----------------------------------------------
;        <<  界面关闭后  >>
; ----------------------------------------------
Function .onGUIEnd
  SetOutPath $TEMP
  RMDir /r "$TEMP\Green"
FunctionEnd





